<html>
    <head>
        <title>模块架构</title>        
    </head>
    <body>
        <script>
            //  模块架构 的 最佳实践 和 约定

                    /*
                        一、解决方案结构

                                1、为每个模块创建一个单独的Visual Studio解决方案。

                                2、将解决方案命名为CompanyName. ModuleName（对于核心ABP模块，它是Voo.Abp.ModuleName）。

                                3、将模块开发为分层的，因此它有几个相互关联的包（项目）。

                                        每个包都有自己的模块定义文件，并显式声明依赖包/模块的依赖关系。

                    */

                    /*
                        二、模块的各种使用模式

                                下图显示了分层良好的模块的包以及这些包之间的依赖关系：

                                    图可见与当前文件夹下 "模块项目依赖关系图.drawio"


                                最终目标是允许应用程序以灵活的方式使用该模块。示例应用程序：

                                    1、（A是一个客户端应用程序 web）单体应用程序使用模块：
                                    
                                                添加对Web 和 Application 层的引用。

                                                结果是：

                                                        应用程序可以显示模块的UI

                                                        它在同一进程中托管应用程序和领域层 （这就是为什么它需要引用数据库集成包）

                                                        此应用程序还为模块的HTTP API提供服务（因为它通过Web包包含HttpApi包）。


                                    2、（B可以是客户端应用程序 web、微服务）将模块作为独立的微服务使用：

                                                添加对HttpApi和Application包的引用。

                                                根据首选项添加对EF Core或MongoDB包之一的引用。

                                                结果是：

                                                    应用程序无法显示模块的UI，因为它没有对Web包的引用。

                                                    它在同一进程中托管应用程序和域层（这就是为什么它需要引用数据库集成包）。

                                                    此应用程序服务于模块的HTTP API（作为应用程序的主要目标）。


                                    3、（C可以是单体程序）只适用模块的UI，但是不托管应用程序的应用服务（只是将其用作由应用程序A或B托管的远程服务）

                                                    添加对Web和HttpApi. Client包的引用。

                                                    为HttpApi.Client包配置远程端点。

                                                    结果是：

                                                            应用程序可以显示模块的UI。

                                                            它不会在同一个进程中托管模块的应用程序层和域层。相反，将其用作远程服务。

                                                            此应用程序还为模块的HTTP API提供服务（因为它通过Web包包含HttpApi包）。


                                    4、(D是客户端应用程序)客户端应用程序(或微服务)，仅将模块用作远程服务 （由A、B 或 C 托管）

                                                    添加对HttpApi. Client包的引用。
                                                    
                                                    为HttpApi. Client包配置远程端点。


                                                    结果是：

                                                        应用程序可以将模块的所有功能用作远程客户端。

                                                        应用程序只是一个客户端，不能为模块的HTTP API提供服务。

                                                        应用程序只是一个客户端，不能显示模块的UI。

                                    5、（E相当于一个代理）托管模块的HTTP API但只将所有请求转发到另一个应用程序（由应用程序A、B或C托管）的代理应用程序：、

                                                    添加对HttpApi和HttpApi. Client包的引用。

                                                    为HttpApi. Client包配置远程端点。

                                                    结果是：

                                                        应用程序可以将模块的所有功能用作远程客户端。

                                                        此应用程序还为模块的HTTP API提供服务，但实际上通过将所有请求（针对模块）重定向到另一个远程服务器来像代理一样工作。

                    */

                    /*
                         三、领域层  Domain Layer

                                做将域层分成两个项目：

                                        1、Domain. Shared包

                                                名为CompanyName.ModuleName.Domain.Shared，其中包含可以与模块所有层安全共享的"常量"、"枚举" 和 "其他类型"。

                                                此包也可以共享给第3方客户端。它不能包含实体、存储库、域服务或任何其他业务对象。


                                         2、Domain包 

                                                领域包，名为CompanyName. ModuleName.Domain，包含 "实体"、"存储库接口"、"域服务接口" 及其 实现和其他域对象。

                                                领域域包依赖于 "Domain. Shared" 包。

                    */

                    /*
                        四、应用层 Application Layer

                                将应用层分成两个项目：

                                          1、Application.Contract  应用程序契约包

                                                 应用程序契约包,名为CompanyName. ModuleName.Application。其中包含 "应用程序服务接口" 和 "相关的数据搬迁对象".

                                                 应用程序契约包依赖于Domain. Shared包。

                                          2、Application 应用程序包

                                                Application包，名为CompanyName. ModuleName.Application，其中包含应用程序服务实现。

                                                应用程序包取决于Domain和Application. Developts包。
                    */

                    /*
                        五、基础设施层  

                                为每个ORM/数据库集成（如Entity Framework Core和MongoDB）创建一个单独的集成包。

                                例如，创建一个CompanyName. ModuleName.EntityFrameworkCore包来抽象Entity Framework Core集成。
                                
                                ORM集成包依赖于Domain包。
                                
                                ORM集成包里只依赖于领域层包。


                                为每个主要库创建一个单独的集成包，计划由另一个库替换，而不影响其他包。
                    */

                    /*
                        六、HTTP API 层

                                1、创建一个Http Api包：

                                        创建一个HTTP API包，名为CompanyName. ModuleName.HttpApi，为模块开发REST风格的HTTP API。

                                            ①、api层只依赖于 "应用程序契约层"，不依赖于其他任何层。

                                            ②、api层为每个应用服务创建一个控制器（通常通过实现它们的接口）。这些控制器使用应用程序服务接口来委派操作。

                                                            它只是在需要时配置路由、HTTP方法和其他与Web相关的东西。


                                2、创建一个Http Api Client包：

                                            名为CompanyName. ModuleName.HttpApi.Client，为HTTP API包提供客户端服务。

                                            这些客户端服务实现应用程序接口作为远程端点的客户端。

                                                HTTP API客户端包仅依赖于Application.Contracts包。

                                                使用ABP的动态HTTP C#客户端代理功能。
                    */

                    /*
                        七、Web UI 层

                                  创建一个Web包，名为CompanyName. ModuleName.Web， 其中包含页面、视图、脚本、样式、图像和其他UI组件。 


                                            Web包仅依赖于HttpApi包。
                    */
        </script>
    </body>
</html>